package com.cinema.dao.impl;

import com.cinema.dao.MovieDao;
import com.cinema.dao.ScheduleDao;
import com.cinema.dao.ScreeningRoomDao;
import com.cinema.db.DatabaseManager;
import com.cinema.entity.Movie;
import com.cinema.entity.Schedule;
import com.cinema.entity.ScreeningRoom;

import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 排片数据访问实现类
 */
public class ScheduleDaoImpl implements ScheduleDao {
    
    private final DatabaseManager dbManager = DatabaseManager.getInstance();
    private final MovieDao movieDao = new MovieDaoImpl();
    private final ScreeningRoomDao roomDao = new ScreeningRoomDaoImpl();
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    
    @Override
    public void addSchedule(Schedule schedule) {
        String sql = "INSERT INTO schedules (id, movie_id, room_id, start_time, end_time) VALUES (?, ?, ?, ?, ?)";
        try {
            dbManager.executeUpdate(sql, schedule.getId(), schedule.getMovie().getId(), 
                                  schedule.getRoom().getId(), 
                                  schedule.getStartTime().format(formatter),
                                  schedule.getEndTime().format(formatter));
            
            // 初始化座位状态
            initializeSeatStatus(schedule);
        } catch (SQLException e) {
            throw new RuntimeException("添加排片失败", e);
        }
    }
    
    @Override
    public Schedule getScheduleById(String id) {
        String sql = "SELECT id, movie_id, room_id, start_time, end_time FROM schedules WHERE id = ?";
        try (ResultSet rs = dbManager.executeQuery(sql, id)) {
            if (rs.next()) {
                return mapResultSetToSchedule(rs);
            }
            return null;
        } catch (SQLException e) {
            throw new RuntimeException("查询排片失败", e);
        }
    }
    
    @Override
    public List<Schedule> getAllSchedules() {
        String sql = "SELECT id, movie_id, room_id, start_time, end_time FROM schedules ORDER BY start_time";
        List<Schedule> schedules = new ArrayList<>();
        try (ResultSet rs = dbManager.executeQuery(sql)) {
            while (rs.next()) {
                schedules.add(mapResultSetToSchedule(rs));
            }
            return schedules;
        } catch (SQLException e) {
            throw new RuntimeException("查询所有排片失败", e);
        }
    }
    
    @Override
    public void updateSchedule(Schedule schedule) {
        String sql = "UPDATE schedules SET movie_id = ?, room_id = ?, start_time = ?, end_time = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?";
        try {
            int rows = dbManager.executeUpdate(sql, schedule.getMovie().getId(), 
                                             schedule.getRoom().getId(),
                                             schedule.getStartTime().format(formatter),
                                             schedule.getEndTime().format(formatter),
                                             schedule.getId());
            if (rows == 0) {
                throw new RuntimeException("排片不存在: " + schedule.getId());
            }
        } catch (SQLException e) {
            throw new RuntimeException("更新排片失败", e);
        }
    }
    
    @Override
    public void deleteSchedule(String id) {
        String sql = "DELETE FROM schedules WHERE id = ?";
        try {
            int rows = dbManager.executeUpdate(sql, id);
            if (rows == 0) {
                throw new RuntimeException("排片不存在: " + id);
            }
        } catch (SQLException e) {
            throw new RuntimeException("删除排片失败", e);
        }
    }
    
    @Override
    public boolean scheduleExists(String id) {
        String sql = "SELECT COUNT(*) FROM schedules WHERE id = ?";
        try (ResultSet rs = dbManager.executeQuery(sql, id)) {
            if (rs.next()) {
                return rs.getInt(1) > 0;
            }
            return false;
        } catch (SQLException e) {
            throw new RuntimeException("检查排片是否存在失败", e);
        }
    }
    
    @Override
    public List<Schedule> getSchedulesByMovie(String movieId) {
        String sql = "SELECT id, movie_id, room_id, start_time, end_time FROM schedules WHERE movie_id = ? ORDER BY start_time";
        List<Schedule> schedules = new ArrayList<>();
        try (ResultSet rs = dbManager.executeQuery(sql, movieId)) {
            while (rs.next()) {
                schedules.add(mapResultSetToSchedule(rs));
            }
            return schedules;
        } catch (SQLException e) {
            throw new RuntimeException("根据电影查询排片失败", e);
        }
    }
    
    @Override
    public List<Schedule> getSchedulesByRoom(String roomId) {
        String sql = "SELECT id, movie_id, room_id, start_time, end_time FROM schedules WHERE room_id = ? ORDER BY start_time";
        List<Schedule> schedules = new ArrayList<>();
        try (ResultSet rs = dbManager.executeQuery(sql, roomId)) {
            while (rs.next()) {
                schedules.add(mapResultSetToSchedule(rs));
            }
            return schedules;
        } catch (SQLException e) {
            throw new RuntimeException("根据放映厅查询排片失败", e);
        }
    }
    
    @Override
    public List<Schedule> getSchedulesByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        String sql = "SELECT id, movie_id, room_id, start_time, end_time FROM schedules WHERE (start_time >= ? AND start_time <= ?) OR (end_time >= ? AND end_time <= ?) OR (start_time <= ? AND end_time >= ?) ORDER BY start_time";
        List<Schedule> schedules = new ArrayList<>();
        try (ResultSet rs = dbManager.executeQuery(sql, 
                startTime.format(formatter), endTime.format(formatter),
                startTime.format(formatter), endTime.format(formatter),
                startTime.format(formatter), endTime.format(formatter))) {
            while (rs.next()) {
                schedules.add(mapResultSetToSchedule(rs));
            }
            return schedules;
        } catch (SQLException e) {
            throw new RuntimeException("根据时间范围查询排片失败", e);
        }
    }
    
    @Override
    public boolean hasTimeConflict(String roomId, LocalDateTime startTime, LocalDateTime endTime, String excludeScheduleId) {
        String sql = "SELECT COUNT(*) FROM schedules WHERE room_id = ? AND id != ? AND ((start_time >= ? AND start_time < ?) OR (end_time > ? AND end_time <= ?) OR (start_time <= ? AND end_time >= ?))";
        try (ResultSet rs = dbManager.executeQuery(sql, roomId, excludeScheduleId,
                startTime.format(formatter), endTime.format(formatter),
                startTime.format(formatter), endTime.format(formatter),
                startTime.format(formatter), endTime.format(formatter))) {
            if (rs.next()) {
                return rs.getInt(1) > 0;
            }
            return false;
        } catch (SQLException e) {
            throw new RuntimeException("检查时间冲突失败", e);
        }
    }
    
    private Schedule mapResultSetToSchedule(ResultSet rs) throws SQLException {
        String id = rs.getString("id");
        String movieId = rs.getString("movie_id");
        String roomId = rs.getString("room_id");
        LocalDateTime startTime = LocalDateTime.parse(rs.getString("start_time"), formatter);
        LocalDateTime endTime = LocalDateTime.parse(rs.getString("end_time"), formatter);
        
        Movie movie = movieDao.getMovieById(movieId);
        ScreeningRoom room = roomDao.getRoomById(roomId);
        
        if (movie == null || room == null) {
            throw new RuntimeException("排片关联的电影或放映厅不存在");
        }
        
        Schedule schedule = new Schedule(id, movie, room, startTime, endTime);
        
        // 加载座位状态
        loadSeatStatus(schedule);
        
        return schedule;
    }
    
    private void initializeSeatStatus(Schedule schedule) {
        ScreeningRoom room = schedule.getRoom();
        String sql = "INSERT INTO seat_status (schedule_id, row_num, col_num, is_occupied) VALUES (?, ?, ?, ?)";
        
        try {
            for (int row = 0; row < room.getRows(); row++) {
                for (int col = 0; col < room.getCols(); col++) {
                    dbManager.executeUpdate(sql, schedule.getId(), row, col, 0);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("初始化座位状态失败", e);
        }
    }
    
    private void loadSeatStatus(Schedule schedule) {
        String sql = "SELECT row_num, col_num, is_occupied, phone FROM seat_status WHERE schedule_id = ? ORDER BY row_num, col_num";
        try (ResultSet rs = dbManager.executeQuery(sql, schedule.getId())) {
            while (rs.next()) {
                int row = rs.getInt("row_num");
                int col = rs.getInt("col_num");
                boolean isOccupied = rs.getInt("is_occupied") == 1;
                String phone = rs.getString("phone");
                
                if (isOccupied) {
                    schedule.getSeatStatus()[row][col] = phone;
                } else {
                    schedule.getSeatStatus()[row][col] = null;
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("加载座位状态失败", e);
        }
    }
} 